package com.btnc.observer;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.Scanner;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.activemq.ActiveMQConnection;
import org.apache.log4j.Logger;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class BtncObserverSystem implements MessageListener {

	private static final Logger logger = Logger
			.getLogger(BtncObserverSystem.class);
	private Map<String, Boolean> userAuthMap;
	private String connectionURL;

	@Override
	public void onMessage(Message btncMessage) {
		if (!(btncMessage instanceof TextMessage)) {
			logger.error("expected message of type TextMessage, ignoring this message");
			return;
		}
		String xmlMessage;
		try {
			xmlMessage = ((TextMessage) btncMessage).getText();
			logger.info("received message " + xmlMessage);
			DocumentBuilderFactory builderFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder builder = builderFactory.newDocumentBuilder();
			Document document = builder.parse(new InputSource(new StringReader(
					xmlMessage)));
			NodeList nodes = document.getElementsByTagName("btnc");
			Element element = (Element) nodes.item(0);

			String type = element.getAttribute("type");

			if (type.equals("auth")) {
				authenticate(element);
			} else if (type.equals("schedule")) {
				getSchedule(element.getAttribute("route"),
						element.getAttribute("date"));

			}

		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (URISyntaxException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void getSchedule(String route, String date) throws JMSException,
			URISyntaxException, FileNotFoundException {
		ActiveMQConnection connection = ActiveMQConnection
				.makeConnection(connectionURL);
		connection.start();
		Session session = connection.createSession(false,
				Session.AUTO_ACKNOWLEDGE);
		Destination output = session.createQueue("btnc.schedule.output");
		MessageProducer producer = session.createProducer(output);
		TextMessage schedule = session.createTextMessage();

		File fFile = new File(
				"/media/harmony/Document/root.workspace/ESB/workspace/BtncProcessManager/movingnote/"
						+ route + "-" + date + ".xml");
		Scanner scanner = new Scanner(new FileReader(fFile));
		String noteXML = "";
		while (scanner.hasNextLine()) {
			noteXML += scanner.nextLine().trim();
		}
		scanner.close();
		schedule.setText(noteXML);
		producer.send(schedule);
		connection.close();
	}

	private void authenticate(Element element) throws Exception {
		String username = getTextValue(element, "user");
		String password = getTextValue(element, "pass");

		logger.info("Username " + username + " Password " + password);

		Boolean verified = false;
		if (userAuthMap.containsKey(username)) {
			verified = (Boolean) userAuthMap.get(username);
		} else {
			logger.error("no user found " + username);
		}

		ActiveMQConnection connection = ActiveMQConnection
				.makeConnection(connectionURL);
		connection.start();
		Session session = connection.createSession(false,
				Session.AUTO_ACKNOWLEDGE);
		Destination output = session.createQueue("btnc.output");
		MessageProducer producer = session.createProducer(output);
		TextMessage verifyMessage = session.createTextMessage();
		verifyMessage.setText(createVerifyMessage(username, verified));
		producer.send(verifyMessage);
		connection.close();
	}

	private String getTextValue(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if (nl != null && nl.getLength() > 0) {
			Element el = (Element) nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}

	private String createVerifyMessage(String username, Boolean verified)
			throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		DOMImplementation impl = builder.getDOMImplementation();
		Document verifyDocument = impl.createDocument(null, "btnc", null);
		Element btncElement = verifyDocument.getDocumentElement();
		Attr typeAttribute = verifyDocument.createAttribute("type");
		typeAttribute.setValue("auth");
		Element userElement = verifyDocument.createElement("user");
		userElement.setTextContent(username);
		Element verifyElement = verifyDocument.createElement("verify");
		verifyElement.setTextContent(verified.toString());
		btncElement.setAttributeNode(typeAttribute);
		btncElement.appendChild(userElement);
		btncElement.appendChild(verifyElement);
		DOMSource domSource = new DOMSource(verifyDocument);
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		StreamResult streamResult = new StreamResult(outputStream);
		TransformerFactory transformerFactory = TransformerFactory
				.newInstance();
		Transformer serializer = transformerFactory.newTransformer();
		serializer.transform(domSource, streamResult);
		return outputStream.toString();

	}

//	@Deprecated
//	private String createDriverTasksMessage(String username,
//			List<Task> usersTasks) throws Exception {
//		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//		DocumentBuilder builder = factory.newDocumentBuilder();
//		DOMImplementation impl = builder.getDOMImplementation();
//		Document tasksDocument = impl.createDocument(null, "btnc", null);
//		Element btncElement = tasksDocument.getDocumentElement();
//		Attr typeAttribute = tasksDocument.createAttribute("type");
//		typeAttribute.setValue("task");
//		Element userElement = tasksDocument.createElement("user");
//		userElement.setTextContent(username);
//		Element tasksElement = tasksDocument.createElement("tasks");
//		tasksElement.setAttribute("number", String.valueOf(usersTasks.size()));
//		for (Task task : usersTasks) {
//			Element taskElement = tasksDocument.createElement("task");
//			Element envelopeElement = tasksDocument.createElement("envelope");
//			envelopeElement.setTextContent(task.getEnvelopeId());
//			taskElement.appendChild(envelopeElement);
//			Element sourcePosElement = tasksDocument.createElement("source");
//			sourcePosElement.setTextContent(task.getSourcePointOfSale());
//			taskElement.appendChild(sourcePosElement);
//			Element destPosElement = tasksDocument.createElement("destination");
//			destPosElement.setTextContent(task.getDestinationPointOfSale());
//			taskElement.appendChild(destPosElement);
//			Element taskTypeElement = tasksDocument.createElement("action");
//			taskTypeElement.setTextContent(task.getTaskType());
//			taskElement.appendChild(taskTypeElement);
//			Element priorityElement = tasksDocument.createElement("priority");
//			priorityElement.setTextContent(String.valueOf(task.getPriority()));
//			taskElement.appendChild(priorityElement);
//			tasksElement.appendChild(taskElement);
//		}
//		btncElement.setAttributeNode(typeAttribute);
//		btncElement.appendChild(userElement);
//		btncElement.appendChild(tasksElement);
//		DOMSource domSource = new DOMSource(tasksDocument);
//		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//		StreamResult streamResult = new StreamResult(outputStream);
//		TransformerFactory transformerFactory = TransformerFactory
//				.newInstance();
//		Transformer serializer = transformerFactory.newTransformer();
//		serializer.transform(domSource, streamResult);
//		return outputStream.toString();
//
//	}

	public Map<String, Boolean> getUserAuthMap() {
		return userAuthMap;
	}

	public void setUserAuthMap(Map<String, Boolean> userAuthMap) {
		this.userAuthMap = userAuthMap;
	}

	public String getConnectionURL() {
		return connectionURL;
	}

	public void setConnectionURL(String connectionURL) {
		this.connectionURL = connectionURL;
	}

}
